#include "njm_game_obj.hpp"

namespace njm
{

    // 矩阵转换
    // 先scale，再rotate，最后translate
    // 旋转顺序：先绕Z轴旋转，再绕X轴旋转，最后绕Y轴旋转
    // glm::mat4 mat4() {
    //     auto transform = glm::translate(glm::mat4(1.f), translation);
    //     transform = glm::rotate(transform, rotation.y, {0.f, 1.f, 0.f});
    //     transform = glm::rotate(transform, rotation.x, {1.f, 0.f, 0.f});
    //     transform = glm::rotate(transform, rotation.z, {0.f, 0.f, 1.f});
    //     transform = glm::scale(transform, scale);
    //     return transform;
    // }
    glm::mat4 TransformComponent::mat4()
    {
        const float c3 = glm::cos(rotation.z);
        const float s3 = glm::sin(rotation.z);
        const float c2 = glm::cos(rotation.x);
        const float s2 = glm::sin(rotation.x);
        const float c1 = glm::cos(rotation.y);
        const float s1 = glm::sin(rotation.y);
        return glm::mat4{
            {
                scale.x * (c1 * c3 + s1 * s2 * s3),
                scale.x * (c2 * s3),
                scale.x * (c1 * s2 * s3 - c3 * s1),
                0.0f,
            },
            {
                scale.y * (c3 * s1 * s2 - c1 * s3),
                scale.y * (c2 * c3),
                scale.y * (c1 * c3 * s2 + s1 * s3),
                0.0f,
            },
            {
                scale.z * (c2 * s1),
                scale.z * (-s2),
                scale.z * (c1 * c2),
                0.0f,
            },
            {translation.x, translation.y, translation.z, 1.0f}};
    }

    glm::mat3 TransformComponent::normalMatrix()
    {
        const float c3 = glm::cos(rotation.z);
        const float s3 = glm::sin(rotation.z);
        const float c2 = glm::cos(rotation.x);
        const float s2 = glm::sin(rotation.x);
        const float c1 = glm::cos(rotation.y);
        const float s1 = glm::sin(rotation.y);
        const glm::vec3 inverseScale = 1.0f / scale;
        return glm::mat3{
            {
                inverseScale.x * (c2 * s3),
                inverseScale.x * (c1 * s2 * s3 - c3 * s1),
                inverseScale.x * (c1 * c3 + s1 * s2 * s3),
            },
            {
                inverseScale.y * (c3 * s1 * s2 - c1 * s3),
                inverseScale.y * (c2 * c3),
                inverseScale.y * (c1 * c3 * s2 + s1 * s3),
            },
            {
                inverseScale.z * (c2 * s1),
                inverseScale.z * (-s2),
                inverseScale.z * (c1 * c2),
            },
        };
    }

    NjmGameObj NjmGameObj::createGameObj()
    {
        static id_t currentId = 0;
        return NjmGameObj(currentId++);
    }
    
    NjmGameObj NjmGameObj::createPointLight(float lightIntensity, float radius, glm::vec3 color)
    {
        NjmGameObj obj = createGameObj();
        obj.color = color;
        obj.transform.scale.x = radius;
        obj.pointLight = std::make_unique<PointLightComponent>();
        obj.pointLight->lightIntensity = lightIntensity;
        return obj;
    }

    NjmGameObj::NjmGameObj(id_t objId) : id{objId}
    {
    }
    NjmGameObj::~NjmGameObj()
    {
    }

}